// https://learn.microsoft.com/en-us/typography/opentype/spec/hmtx

use super::*;

#[derive(Debug, Clone)]
pub struct Table<'a> {
	pub metrics: LazyArray16<'a, Metrics>, // A list of metrics indexed by glyph ID.
	pub bearings: LazyArray16<'a, FWORD>,  // Side bearings for glyph IDs greater than or equal to the number of `metrics` values.
}
impl<'a> Table<'a> {
	pub fn parse(num_metrics: u16, num_glyphs: u16, data: &'a [u8]) -> Option<Self> {
		let num_bearings = num_glyphs.checked_sub(num_metrics);
		let mut s = Stream::new(data);
		Some(Table {
			metrics: s.read_array16(num_metrics)?,
			bearings: s.read_array16(num_bearings.unwrap_or(0))?,
		})
	}
	#[inline]
	pub fn advance(&self, glyph_id: u16) -> Option<u16> {
		if let Some(metrics) = self.metrics.get(glyph_id) {
			Some(metrics.advance)
		} else {
			// 'As an optimization, the number of records can be less than the number of glyphs,
			// in which case the advance value of the last record applies
			// to all remaining glyph IDs.'
			self.metrics.get(self.metrics.len().checked_sub(1)?).map(|m| m.advance)
		}
	}
	/// Returns side bearing for a glyph.
	#[inline]
	pub fn side_bearing(&self, glyph_id: u16) -> Option<i16> {
		if let Some(metrics) = self.metrics.get(glyph_id) {
			Some(metrics.side_bearing)
		} else {
			// 'If the number_of_metrics is less than the total number of glyphs,
			// then that array is followed by an array for the side bearing values
			// of the remaining glyphs.'
			self.bearings.get(glyph_id.checked_sub(self.metrics.len())?)
		}
	}
}

/// Horizontal/Vertical Metrics.
#[derive(Clone, Copy)]
pub struct Metrics {
	pub advance: UFWORD,     // Width/Height advance for `hmtx`/`vmtx`. in font design units.
	pub side_bearing: FWORD, // Left/Top side bearing for `hmtx`/`vmtx`.in font design units.
}
impl FromData for Metrics {
	const SIZE: usize = 4;
	#[inline]
	fn parse(data: &[u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Metrics {
			advance: s.read::<u16>()?,
			side_bearing: s.read::<i16>()?,
		})
	}
}
impl core::fmt::Debug for Metrics {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		f.write_fmt(format_args!("Metrics({},{})", self.advance, self.side_bearing))
	}
}
